home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 6
/
Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso
/
016a
/
nansi30.zip
/
RAW.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-14
|
7KB
|
215 lines
/*--- raw.c --------------------------------------------------------------
MS-DOS routines to set and reset raw mode, enable or disable break checking,
and check for characters on stdin.
Written by Dan Kegel (dank@moc.jpl.nasa.gov). Enjoy.
$Log: raw.c $
* Revision 1.3 90/07/14 09:02:03 dan_kegel
* Added raw_set_stdio(), which should make it easy to use RAW mode.
*
* Revision 1.2 90/07/09 23:18:15 dan_kegel
* Compiles with /w3 now.
*
* Revision 1.1 90/07/09 23:11:13 dan_kegel
* Initial revision
*
QUICK SUMMARY:
For fast screen output, call
raw_set_stdio(1);
at the beginning of your program, and
raw_set_stdio(0);
at the end, and use getchar() to grab keystrokes from the keyboard.
Your screen updates will be much faster (assuming you use stdout, and
have installed NANSI.SYS or FANSI-CONSOLE), and
getchar() will treat Backspace, Enter, ^S, ^C, ^P, and ESC as normal
keystrokes rather than as editing characters.
DETAILS and extra goodies:
To maximize display speed, applications should set the stdout device to
raw mode when they start up, and clear it when they exit or start up a
subshell.
It is the device associated with a file handle that has a RAW mode, not
the file handle itself. Thus, if stdin and stdout both refer to CON:,
raw_get(fileno(stdin)) will always equal raw_get(fileno(stdout)).
The stdin device should not be in RAW mode during normal operation
because this disables normal command-line editing. For example,
COPY CON: NUL: will never exit if stdin is in RAW mode.
Because RAW mode is dangerous, applications that use it should prevent
DOS from checking for Control-C or Control-Break. This can be done by
calling break_set(0).
To check for an input char without waiting, call raw_kbhit().
Be sure to turn off break checking before you call, unless you want
the user to be able to break out of your program!
To use getchar() while the console is in RAW mode, you must first disable
input buffering by executing
setbuf(stdin, NULL);
or else getchar() will simply hang.
When stdin is in RAW mode, getchar() will not check for control-C,
control-S, or control-P; it will also not echo.
(The ideas here are all UNIX-compatible, but the following code would
need changes to compile under UNIX. Under UNIX, the only reason to
use RAW mode is to cause getchar() to not check for ^C, ^S, etc.)
If you tend to do lots of single-character outputting to the screen,
you may need to use output buffering before you see any speed benefits from
RAW mode. If you use putchar() to do your outputs, you can enable output
buffering by executing
static char stdoutbuf[BUFSIZ];
setbuf(stdout, stdoutbuf);
but then you you have to fflush(stdout) each time you want to be sure your
output has made it out of the buffer onto the screen.
--------------------------------------------------------------------------*/
#include <dos.h>
#include <stdio.h>
#include "raw.h"
/* IOCTL GETBITS/SETBITS bits. */
#define DEVICE 0x80
#define RAW 0x20
/* IOCTL operations */
#define GETBITS 0
#define SETBITS 1
#define GETINSTATUS 6
/* DOS function numbers. */
#define BREAKCHECK 0x33
#define IOCTL 0x44
/* A nice way to call the DOS IOCTL function */
static int
ioctl(int handle, int mode, unsigned setvalue)
{
union REGS regs;
regs.h.ah = IOCTL;
regs.h.al = (char) mode;
regs.x.bx = handle;
regs.h.dl = (char) setvalue;
regs.h.dh = 0; /* Zero out dh */
intdos(®s, ®s);
return (regs.x.dx);
}
/*--------------------------------------------------------------------------
Call this routine to determinte whether the device associated with
the given file is in RAW mode.
Returns FALSE if not in raw mode, TRUE if in raw mode.
Example: old_raw = raw_get(fileno(stdin));
--------------------------------------------------------------------------*/
int
raw_get(fd)
int fd;
{
return ( RAW == (RAW & ioctl(fd, GETBITS, 0)));
}
/*--------------------------------------------------------------------------
Call this routine to set or clear RAW mode for the device associated with
the given file.
Example: raw_set(fileno(stdout), TRUE);
--------------------------------------------------------------------------*/
void
raw_set(fd, raw)
int fd;
int raw;
{
int bits;
bits = ioctl(fd, GETBITS, 0);
if (DEVICE & bits) {
if (raw)
bits |= RAW;
else
bits &= ~RAW;
(void) ioctl(fd, SETBITS, bits);
}
}
/*--------------------------------------------------------------------------
If any input is ready on stdin, return a nonzero value.
Else return zero.
This works for both input files and devices.
In RAW mode, if break checking is turned off, does not check for ^C.
(The kbhit() that comes with Microsoft C seems to always check for ^C.)
----------------------------------------------------------------------------*/
int
raw_kbhit()
{
union REGS regs;
regs.h.ah = IOCTL;
regs.h.al = GETINSTATUS;
regs.x.bx = fileno(stdin);
intdos(®s, ®s);
return (0xff & regs.h.al);
}
/* A nice way to call the DOS BREAKCHECK function */
static int
breakctl(int mode, int setvalue)
{
union REGS regs;
regs.h.ah = BREAKCHECK;
regs.h.al = (char) mode;
regs.h.dl = (char) setvalue;
intdos(®s, ®s);
return (regs.x.dx & 0xff);
}
/*--------------------------------------------------------------------------
Call this routine to determine whether DOS is checking for break (Control-C)
before it executes any DOS function call.
Return value is FALSE if it only checks before console I/O function calls,
TRUE if it checks before any function call.
--------------------------------------------------------------------------*/
int
break_get(void)
{
return ( 0 != breakctl(GETBITS, 0));
}
/*--------------------------------------------------------------------------
Call this routine with TRUE to tell DOS to check for break (Control-C)
before it executes any DOS function call.
Call this routine with FALSE to tell DOS to only check for break before
it executes console I/O function calls.
--------------------------------------------------------------------------*/
void
break_set(check)
int check;
{
(void) breakctl(SETBITS, check);
}
/*--------------------------------------------------------------------------
One routine to set (or clear) raw mode on stdin and stdout,
clear (or restore) break checking, and turn off input buffering on stdin.
This is the most common configuration; under MS-DOS, since setting raw mode
on stdout sometimes sets it on stdin, it's best to set it on both & be done
with it.
--------------------------------------------------------------------------*/
void
raw_set_stdio(raw)
int raw; /* TRUE -> set raw mode; FALSE -> clear raw mode */
{
static int was_break_checking = 0;
raw_set(fileno(stdin), raw);
raw_set(fileno(stdout), raw);
if (raw) {
setbuf(stdin, NULL); /* so getchar() won't hang */
was_break_checking = break_get();
break_set(0);
} else {
break_set(was_break_checking);
}
}